<?php

namespace C\L;

use Phalcon\Mvc\Controller as PhalconController;
use Phalcon\Paginator\Factory;
use Phalcon\Http\Response;

class Controller extends PhalconController
{
    protected $service;
    protected $params;
    protected $hideKeys;
    protected $showKeys;
    protected $timeToDateKeys = [
    'addtime', 'uptime'
    ];
    protected $updateKeys = [];
    protected $createKeys = [];
    protected $uid = 0;
    protected $ssidKey = '';

    protected $keyworkSearchKeys;
    protected $pubSearchKeys;
    protected $likeSearchKeys;
    protected $regChannelSearchKeys;

    protected $searchLimit = 10;

    protected function onConstruct()
    {
        $router = $this->router->getMatches();
        $publicUrls = $this->config->get('config')['public_api_urls']->toArray();
        // $this->ssidKey = $this->getValue('ssid', false, 'alphanum');
        // if (!$this->ssid->exists($this->ssidKey)) {
        //     if (!in_array($router[0], $publicUrls)) {
        //         $this->error(null, 'E1001');
        //     }
        // }

        if ($this->ssidKey) {
            $this->ssid->register($this->ssidKey);
        }
        $this->uid = $this->ssid->get('uid');


        $this->checkMaintain();
        $this->checkLogin();
        $this->init();
    }

    protected function checkMaintain()
    {
        return true;
    }

    protected function checkLogin()
    {
        return true;
    }

    protected function init()
    {
        return true;
    }

    protected function error($message = null, $code = null)
    {
        $errorMessage = $code == null
          ? $message ?? $this->di['message']->getSerMsg() ?? '操作失败'
          : $this->config->get('error')[$code];

        return $this->echoJson(
            $code ?? 0,
            $errorMessage,
            null
        );
    }

    protected function success($data = [])
    {
        $message = $this->config->get('error')['S0000'];

        return $this->echoJson('S0000', $message, $data);
    }

    public function sqlSensitiveWords($params_str)
    {
        $words = [
        'select', 'create', 'insert', 'update', 'delete',
        'join', 'script', 'alert', 'like', 'union', 'sleep',
        'from', 'where', 'concat', 'char', '`', '\*'
        ];
        foreach ($words as $small) {
            if (is_string($params_str)) {
                if (strpos($params_str, $small) != false) {
                    $this->error('参数不合法');
                }
            }
            if (is_array($params_str)) {
                foreach ($params_str as $k => $v) {
                    if (strpos($k, $small) != false) {
                        $this->error('参数不合法');
                    }
                    if (strpos($v, $small) != false) {
                        $this->error('参数不合法');
                    }
                }
            }
        }
        return true;
    }


    protected function getValue($key = 'id', $check = false, $type = 'trim')
    {
        $value = $this->request->get($key, $type);
        if (empty($value)) {
            $value = $this->request->getPost($key, $type);
        }

        if (is_array($check) && !in_array($value, $check)) {
            $this->error('参数错误');
        }

        if ($check && (!isset($_GET[$key]) && !isset($_POST[$key]))) {
            $this->error('参数错误');
        }

        if ($type == 'int') {
            if (strlen($value) > 9) {
                $this->error('数字过大，服务器要崩溃了');
            }
        }

        if (empty($value) && !isset($_GET[$key]) && !isset($_POST[$key])) {
            $value = null;
        }

        $this->sqlSensitiveWords($value);

        return $value;
    }


    protected function beforeSearch()
    {
        return true;
    }

    protected function afterSearch(&$data)
    {
        return true;
    }

    public function searchAction()
    {
        if (empty($this->service)) {
            $this->error();
        }

        $this->params = [
        'data' => [],
        'data_type' => [],
        'columns' => [],
        'order' => '',
        ];

        if (empty($this->params['page_curren'])) {
            $this->params['page_curren'] = $this->getValue('page_curren', false, 'int') ?: 1;
        }
        if (empty($this->params['page_num'])) {
            $this->params['page_num'] = $this->getValue('page_num', false, 'int') ?: $this->searchLimit;
        }

        $this->setSearchParams();

        if (!$this->beforeSearch()) {
            $this->error('请求失败');
        }

        $data = empty($this->params['data']) ? [] : $this->params['data'];
        $dataType = empty($this->params['data_type']) ? [] : $this->params['data_type'];
        $columns = empty($this->params['columns']) ? [] : $this->params['columns'];
        $order = empty($this->params['order']) ? '' : $this->params['order'];

        $list = $this->service->searchPage(
            $data,
            $dataType,
            $columns,
            $order,
            $this->params['page_curren'],
            $this->params['page_num']
        );

        $this->setHide($list);
        $this->setShow($list);
        $this->setStatusName($list);
        $this->autoTimeToDate($list);

        $data = [
        'list' => $list,
        'count' => $this->service->getCount($data, $dataType),
        'page_num' => $this->params['page_num'],
        'page_curren' => $this->params['page_curren'],
        ];

        $data['config'] = $this->service->getStatusConfig();
        if (!$this->afterSearch($data)) {
            $this->error('请求失败');
        }

        $data['list'] = array_values($data['list']);
        $this->success($data);
    }

    protected function setSearchParams()
    {
        $params = array_merge($this->request->getPost(), $this->request->get());
        foreach ($params as $key => $value) {
            $skey = '';
            if (strstr($key, 'begin_')) {
                $skey = 'begin_';
            }
            if (strstr($key, 'end_')) {
                $skey = 'end_';
            }

            if (empty($skey) || empty($value)) {
                continue;
            }

            $keys = explode($skey, $key);
            if (empty($key[1]) || !empty($this->params['data'][$keys[1]])) {
                continue;
            }

            $beginKey = 'begin_' . $keys[1];
            $endKey = 'end_' . $keys[1];

            $beginNumber = 0;
            $endNumber = 0;
            if (empty($params[$beginKey]) && empty($params[$endKey])) {
                continue;
            }

            if (!empty($params[$beginKey])) {
                $beginTime = strtotime($params[$beginKey]);
                $beginNumber = $this->isDate($params[$endKey]) ? $beginTime : intval($params[$beginKey]);
            }

            if (!empty($params[$endKey])) {
                $endNumber = $this->isDate($params[$endKey]) ?
                strtotime($params[$endKey]) + 24 * 3600 - 1 : intval($params[$endKey]);
            }

            unset($params[$beginKey]);
            unset($params[$endKey]);

            if ($beginNumber && $endNumber) {
                $this->params['data'][$keys[1]] = [$beginNumber, $endNumber];
                $this->params['data_type'][$keys[1]] = "between";
            } elseif ($beginNumber) {
                $this->params['data'][$keys[1]] = $beginNumber;
                $this->params['data_type'][$keys[1]] = '>=';
            } elseif ($endNumber) {
                $this->params['data'][$keys[1]] = $endNumber;
                $this->params['data_type'][$keys[1]] = '<=';
            }
        }
      // endtime
        if (!empty($params['begin_end_time']) && !empty($params['end_end_time'])) {
            $this->params['data']['end_time'] = [
            strtotime($params['begin_end_time']),
            strtotime(date('Y-m-d', strtotime($params['end_end_time']))) + 24 * 3600 - 1
            ];
            $this->params['data_type']['end_time'] = 'between';
        }
        if (!empty($params['keyword_search_value']) && !empty($this->keyworkSearchKeys)) {
            $count = count($this->keyworkSearchKeys);
            foreach ($this->keyworkSearchKeys as $i => $key) {
                if ($key == 'uid') {
                    $keyword = $this->getValue('keyword_search_value');
                    if (!empty($keyword)) {
                        $users = $this->s_user->searchPage(
                            ['mobile' => " (mobile like '%{$keyword}' or name like '%{$keyword}') "],
                            ['mobile' => 'sql']
                        );
                        if (!empty($users)) {
                                $this->params['data']['uid'] = array_column($users, 'uid');
                                $this->params['data_type']['uid'] = 'in';
                        } else {
                              $this->params['data']['uid'] = -1;
                        }
                    }
                } else {
                    $type = '|';
                    $this->params['data'][$key] = $params['keyword_search_value'];

                    if ($count > 1) {
                        if ($i == 0) {
                            $type = '|%';
                        }

                        if ($i == $count - 1) {
                            $type = '%|';
                        }
                    } else {
                        $type = '%';
                    }

                    $this->params['data_type'][$key] = $type;
                }
            }
        }
        if (!empty($this->regChannelSearchKeys) && !empty($params['reg_channel'])) {
            foreach ($this->regChannelSearchKeys as $i => $key) {
                if ($key == 'reg_channel') {
                    $reg_channel = $this->getValue('reg_channel');
                    if (!empty($reg_channel)) {
                        $items = $this->s_user->searchAll(['channel' => $reg_channel]);
                        print_r($items);
                        die;
                        if (!empty($items)) {
                              $this->params['data']['uid'] = array_column($items, 'uid');
                              $this->params['data_type']['uid'] = 'in';
                        } else {
                            $this->params['data']['uid'] = -1;
                        }
                    }
                    // print_r($this->params);die;
                }
            }
        }

        if (!empty($this->pubSearchKeys)) {
            foreach ($this->pubSearchKeys as $key) {
                $value = $this->getValue($key);
                if (!empty($value)) {
                    $this->params['data'][$key] = $value;
                    if (is_array($value)) {
                        $this->params['data_type'][$key] = 'in';
                    }
                }
            }
        }

        if (!empty($this->likeSearchKeys)) {
            foreach ($this->likeSearchKeys as $key) {
                $value = $this->getValue($key);
                if (!empty($value)) {
                    $this->params['data'][$key] = $value;
                    $this->params['data_type'][$key] = 'like';
                }
            }
        }

        return true;
    }

    protected function isDate($dateString)
    {
        return strtotime(date('Y-m-d', strtotime($dateString))) === strtotime($dateString);
    }

    protected function setStatusName(&$data, $service = '')
    {
        if ($service) {
            $config = $this->$service->getStatusConfig();
        } else {
            $config = $this->service->getStatusConfig();
        }
        if (isset($data[0])) {
            foreach ($data as $key => &$value) {
                foreach ($value as $k => $v) {
                    if (array_key_exists($k, $config)) {
                        $value[$k . '_name'] = key_exists($v, $config[$k]) ? $config[$k][$v] : '暂无';
                    }
                }
            }
        } else {
            foreach ($data as $k => &$v) {
                if (array_key_exists($k, $config)) {
                    $data[$k . '_name'] = array_key_exists($v, $config[$k]) ? $config[$k][$v] : '暂无';
                }
            }
        }

        return true;
    }

    protected function setHide(&$data)
    {
        if ($this->hideKeys) {
            if (isset($data[0])) {
                foreach ($data as &$value) {
                    foreach ($value as $k => $v) {
                        if (in_array($k, $this->hideKeys)) {
                            unset($value[$k]);
                        }
                    }
                }
            } else {
                foreach ($data as $k => $v) {
                    if (in_array($k, $this->hideKeys)) {
                        unset($data[$k]);
                    }
                }
            }
        }
    }

    protected function setShow(&$data)
    {
        if ($this->showKeys) {
            if (isset($data[0])) {
                foreach ($data as &$value) {
                    foreach ($value as $k => $v) {
                        if (!in_array($k, $this->showKeys)) {
                            unset($value[$k]);
                        }
                    }
                }
            } else {
                foreach ($data as $k => $v) {
                    if (!in_array($k, $this->showKeys)) {
                        unset($data[$k]);
                    }
                }
            }
        }
    }

    protected function autoTimeToDate(&$data)
    {
        if ($this->timeToDateKeys) {
            $this->setTimeToDate($data, $this->timeToDateKeys);
        }

        return true;
    }

    protected function setTimeToDate(&$data, $keys)
    {
        if (isset($data[0])) {
            foreach ($data as &$value) {
                foreach ($value as $k => $v) {
                    if (in_array($k, $keys)) {
                        $value[$k . '_date'] = $v > 0 ? date('Y-m-d H:i:s', $v) : '暂无时间';
                    }
                }
            }
        } else {
            foreach ($data as $k => &$v) {
                if (in_array($k, $keys)) {
                    $data[$k . '_date'] = $v > 0 ? date('Y-m-d H:i:s', $v) : '暂无时间';
                }
            }
        }

        return true;
    }

    public function viewAction()
    {
        if (empty($this->service)) {
            $this->error();
        }

        if (!$this->beforeView()) {
            $this->error('操作失败');
        }

        $id = $this->getValue('id', true, 'int');
        if (empty($id)) {
            $id = $this->params;
        }

        $view = $this->service->search($id);
        if (empty($view)) {
            $this->error('无数据');
        }

        $this->setHide($view);
        $this->setShow($view);
        $this->setStatusName($view);
        $this->autoTimeToDate($view);

        $data = [
        'view' => $view,
        ];

        $data['config'] = $this->service->getStatusConfig();
        if (!$this->afterView($data)) {
            $this->error('操作失败');
        }

        $this->success($data);
    }

    protected function beforeView()
    {
        return true;
    }

    protected function afterView(&$data)
    {
        return true;
    }

    public function updateAction()
    {
        if (empty($this->service)) {
            $this->error();
        }

        $this->params = [
        'update' => [],
        ];

        $id = $this->getValue('id');
        if (empty($id)) {
            $id = $this->params;
        }

        $update = $this->setUpdateVlaue();
        if (!$this->beforeUpdate($update)) {
            $this->error('操作失败');
        }

        $data = ['id' => $id];
        if (empty($update)) {
            $this->success($data);
        }

        if (!$this->service->update($id, $update)) {
            $this->error('无数据');
        }

        if (!$this->afterUpdate($data)) {
            $this->error('操作失败');
        }

        $this->success($data);
    }

    protected function beforeUpdate(&$data)
    {
        return true;
    }

    protected function afterUpdate(&$data)
    {
        return true;
    }

    protected function setUpdateVlaue()
    {
        $update = [];
        $config = $this->service->getStatusConfig();
        if (!empty($this->updateKeys)) {
            foreach ($this->updateKeys as $v) {
                if ($this->checkPostValueInit($v)) {
                    $value = $this->getValue($v);
                    if (array_key_exists($v, $config)) {
                        if (array_key_exists($value, $config[$v])) {
                            $update[$v] = $value;
                        }
                    } else {
                        $update[$v] = $value;
                    }
                }
            }
        }

        return $update;
    }

    public function removeAction()
    {
        if (empty($this->service)) {
            $this->error();
        }

        if (!$this->beforeRemove()) {
            $this->error('操作失败');
        }

        $id = $this->getValue('id', true);

        if (empty($id)) {
            $this->error('操作失败');
        }

        if (!$this->service->update($id, ['is_delete' => 1])) {
            $this->error('无数据');
        }

        $data = ['id' => $id];
        if (!$this->afterRemove($data)) {
            $this->error('操作失败');
        }

        $this->success($data);
    }

    protected function afterRemove(&$data)
    {
        return true;
    }

    protected function beforeRemove()
    {
        return true;
    }


    public function createAction()
    {
        if (empty($this->service)) {
            $this->error();
        }

        $this->params = [
        'create' => [],
        ];

        $add = $this->setCreateData();

        if (!$this->beforeCreate($add)) {
            $this->error('操作失败');
        }

        if (empty($add)) {
            $this->error();
        }

        if (!$id = $this->service->save($add)) {
            $this->error('无数据');
        }

        $data = ['id' => $id];
        if (!$this->afterCreate($data)) {
            $this->error('操作失败');
        }

        $this->success($data);
    }

    protected function afterCreate(&$data)
    {
        return true;
    }

    protected function beforeCreate(&$data)
    {
        return true;
    }

    protected function setCreateData()
    {
        $data = [];
        $config = $this->service->getStatusConfig();

        if (!empty($this->createKeys)) {
            foreach ($this->createKeys as $v) {
                if ($this->checkPostValueInit($v)) {
                    $value = $this->getValue($v);
                    if (array_key_exists($v, $config)) {
                        if (array_key_exists($value, $config[$v])) {
                            $data[$v] = $value;
                        }
                    } else {
                        $data[$v] = $value;
                    }
                }
            }
        }

        return $data;
    }

    protected function checkPostValueInit($key)
    {
        return $this->checkValueInit($key, $_GET) || $this->checkValueInit($key, $_POST);
    }

    protected function checkValueInit($key, $array = [])
    {
        if (isset($array[$key])) {
            return true;
        }

        return false;
    }

    public function configAction()
    {
        if (empty($this->service)) {
            $this->error();
        }

        $this->success($this->service->getStatusConfig());
    }

    protected function paginationByBuilder($builder, $currentPage, $perPage)
    {
        $options = [
        'builder' => $builder,
        'limit'   => $perPage,
        'page'    => $currentPage,
        'adapter' => 'queryBuilder',
        ];

        $pagination = Factory::load($options)->getPaginate();

        $result = [
        'items' => $pagination->items,
        'pagination' => [
        'total'        => $pagination->total_items,
        'per_page'     => $pagination->limit,
        'total_page'   => $pagination->total_pages,
        'current_page' => $pagination->current,
        ],
        ];

        return $result;
    }

    // --- New ---
    protected function convertAssetsUrl($path)
    {
        if (!$path) {
            return null;
        }

        $config = $this->config->get('config');

        return $config['base_url'] . $path;
    }

    private function echoJson($code, $message, $data)
    {
        $json = compact('code', 'message', 'data');

        if (APP_MODE == 'dev') {
            $json['dev_show_msg'] = implode('|', [
                $this->config->get('error')[$message],
                $this->message->getSerMsg(),
                $this->message->getCodeMsg()
            ]);
        }

        if ($this->ssid->get('is_login') == 'Y') {
            $this->cache->zAdd('login_user', $this->ssid->get('uid'), time());
        }

        $json = array_merge($json, [
            'btime' => $_SERVER['REQUEST_TIME'],
            'etime' => time(),
            'ssid'  => $this->ssidKey,
        ]);

        $this->weblog->alert(json_encode($json, JSON_UNESCAPED_UNICODE));

        return $this->response(json_encode($json,JSON_UNESCAPED_UNICODE));
    }

    protected function response($data, $statusCode = 200)
    {
        $response = new Response;
        $response->setStatusCode($statusCode, 'OK');
        $response->setHeader('Content-Type', 'application/json; charset=UTF-8');
        $response->setHeader("Access-Control-Allow-Origin", '*');
        $response->setHeader("Access-Control-Allow-Methods", 'GET,PUT,POST,DELETE,OPTIONS');
        $response->setHeader(
            "Access-Control-Allow-Headers",
            'Origin, X-Requested-With, Content-Range, Content-Type, Authorization'
        );
        $response->setHeader("Access-Control-Allow-Credentials", true);
        $response->setContent($data);
        $response->send();

        exit();
    }

    protected function responseBinary($data, $statusCode = 200)
    {
        $response = new Response;
        $response->setStatusCode($statusCode, 'OK');
        $response->setHeader('Content-Type', $data['content_type']);
        $response->setHeader("Access-Control-Allow-Origin", '*');
        $response->setHeader("Access-Control-Expose-Headers", 'Content-Disposition');
        $response->setHeader(
            "Content-Disposition",
            'Content-Disposition: attachment;filename="'.$data['filename'].'"'
        );
        $response->setHeader("Cache-Control", "max-age=0");
        $response->setContent($data['content']);
        $response->send();
    }
}
